            
{ Copyright (C) 2009, Serge Voloshenyuk
  
  This file is Free Software and part of DCocoR
  
  It is licensed under the following three licenses as alternatives:
    1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
    2. GNU General Public License (GPL) V2 or any newer version
    3. Apache License, V2.0 or any newer version
  
  You may not use this file except in compliance with at least one of
  the above three licenses.
  
  See LICENSE.txt at the top of this package for the
  complete terms and further detail along with the license texts for
  the licenses in COPYING-LIB.txt, COPYING.txt and LICENSE-2.0.txt respectively.
} 

{ This unit was generated by DCocoR.  
  Any code in this file that you edit manually will be over-written when the file is regenerated.
}

unit CocoCompiler;

interface

uses Classes,CocoAncestor,
SysUtils,Contnrs, CocoSets, CRTypes, CRT, CRA, Coco, ParserGen;

type


  TCocoCompilerScanner = class(TCocoRScanner)
  public
    procedure SkipIgnoreSet; override;
    procedure ScanSym(state: Integer; var sym: Integer); override;
    
  end;


  TCocoCompiler = class(TCocoRGrammar)
  private                
    fFlagStack: TStack;
    fFrameName: String;
    fErrors, fMetaErrors: TObjectList;
    procedure setFrameName(const Value: String);
    procedure AddToErrorList(var list: TObjectList; aErrorType,aErrorCode, aLine,aCol: Integer;
      const aMsg, aData: string);
 
  protected
                 
    procedure ErrorHandler(Sender: TObject; aErrorType,aErrorCode, aLine,aCol: Integer;
      const aMsg, aData: string);
    procedure MetaErrorHandler(Sender: TObject; aErrorType,aErrorCode, aLine,aCol: Integer;
      const aMsg, aData: string);
    procedure PushFlag;
    function  PopFlag: Boolean;
    function  PeakFlag: Boolean;
    procedure PrintText;
    procedure PrintVar(const name: String);
    function getSortedErrors: TList;
    function Generate: Boolean;
 
    procedure _CocoCompiler;
    procedure _TargetClause;
    procedure _Body;
    procedure _TemplateBlock;
    procedure _Predicate(var value: Boolean );
    procedure _TargetCode;
    procedure _Settings;
    procedure _Param;
    procedure _BoolTerm(var value: Boolean );
    procedure _BoolFactor(var value: Boolean );
    procedure _SystemPridicate(var value: Boolean);

  public
              
    GenFlag: Boolean;
    Parser: TCoco;
    Tab: TSymbolTable;
    DFA: TAutomaton;
    Generator: TParserGenerator;
    
    destructor Destroy; override;
    function Compile(const ResName: String): Boolean; overload;
 

    function  ErrorMessage(ErrorType,ErrorCode: Integer; const data: string): String; override;
    function  TokenToString(n: Integer): String; override;
    function  CreateScanner: TBaseScanner; override;
    function Execute: Boolean; override;

    constructor Create(AOwner: TComponent); override;
                 
 property FrameName: String read fFrameName write setFrameName;
 property Errors: TObjectList read fErrors;
 property MetaErrors: TObjectList read fMetaErrors;

  end;

implementation

const

	identSym = 1;	stringSym = 2;	numberSym = 3;	TARGETSym = 4;	_less_barSym = 5;
	_hashSym = 6;	_querySym = 7;	ELSESym = 8;	ENDSym = 9;	ERRORSym = 10;
	_equalSym = 11;	_bangSym = 12;	_atSym = 13;	_lparenSym = 14;	_rparenSym = 15;
	_bar_greaterSym = 16;	DELETABLESLISTSym = 17;	FIRSTFOLLOWLISTSym = 18;	XREFLISTSym = 19;	LISTINGSym = 20;
	SYMBOLTABLESym = 21;	STATESSym = 22;	NODESSym = 23;	GRAMMASym = 24;	PARSERDECLARATIONSSym = 25;
	TOKENSSym = 26;	INITSTARTSTATESSym = 27;	COMMENTSSym = 28;	INITLITERALSSym = 29;	INITSYMSETSSym = 30;
	ERRORSSym = 31;	SCANSYMSym = 32;	IGNORESETSym = 33;	PARSERIMPLEMENTATIONSym = 34;	TOKENSTRINGSSym = 35;
	ANYANDSYNCSETSSym = 36;	PRAGMASSym = 37;	NOSYMSym = 38;	_commaSym = 39;	ORSym = 40;
	ANDSym = 41;	NOTSym = 42;	DEFINEDSym = 43;	TRUESym = 44;	FALSESym = 45;
	OKSym = 46;	DELETABLESEXISTSym = 47;	IGNORECASESym = 48;	HASHOMOGRAPHSym = 49;	GENSCANNERSym = 50;
	HASCTXMOVESSym = 51;	HASWARNINGSSym = 52;	_NOSYMB = 53;

var CocoCompilerSymSets: TSetArray;


var
  CocoCompilerST: TStartTable = nil;
  CocoCompilerLiterals: TStringList = nil;

{ TCocoCompilerScanner }

procedure TCocoCompilerScanner.ScanSym(state: Integer; var sym: Integer);
begin
 while True do
 begin
  NextCh;
  case state of
	 1:
		if ((CurrInputCh>='0')and(CurrInputCh<='9'))or((CurrInputCh>='A')and(CurrInputCh<='Z'))or(CurrInputCh='_') then
		else begin
		  sym := identSym;
		  CheckLiteral(sym);
		  Exit;
		end;
	 2:
		if (CurrInputCh=' ')or(CurrInputCh='!')or(CurrInputCh>='#') then
		else if (CurrInputCh = '"') then
		  state := 3
		else begin
		  sym := _NOSYMB;
		  Exit;
		end;
	 3:
		begin
		  sym := stringSym;
		  Exit;
		end;
	 4:
		if ((CurrInputCh>='0')and(CurrInputCh<='9')) then
		else begin
		  sym := numberSym;
		  Exit;
		end;
	 5:
		if (CurrInputCh = '|') then
		  state := 6
		else begin
		  sym := _NOSYMB;
		  Exit;
		end;
	 6:
		begin
		  sym := _less_barSym;
		  Exit;
		end;
	 7:
		begin
		  sym := _hashSym;
		  Exit;
		end;
	 8:
		begin
		  sym := _querySym;
		  Exit;
		end;
	 9:
		begin
		  sym := _equalSym;
		  Exit;
		end;
	10:
		begin
		  sym := _bangSym;
		  Exit;
		end;
	11:
		begin
		  sym := _atSym;
		  Exit;
		end;
	12:
		begin
		  sym := _lparenSym;
		  Exit;
		end;
	13:
		begin
		  sym := _rparenSym;
		  Exit;
		end;
	14:
		if (CurrInputCh = '>') then
		  state := 15
		else begin
		  sym := _NOSYMB;
		  Exit;
		end;
	15:
		begin
		  sym := _bar_greaterSym;
		  Exit;
		end;
	16:
		begin
		  sym := _commaSym;
		  Exit;
		end;
  
    else begin
      if CurrInputCh=#0 then
           sym := _EOFSYMB
      else sym := _NOSYMB;
      Exit;
    end;
  end;
 end;
end;


procedure TCocoCompilerScanner.SkipIgnoreSet;
begin
  while (CurrInputCh = ' ') or 
    ( (CurrInputCh=#9)or(CurrInputCh=#10)or(CurrInputCh=#13) )
  do NextCh;
end;




{ TCocoCompiler }

                    
 
destructor TCocoCompiler.Destroy;
begin
  fFlagStack.Free;
  fErrors.Free;
  fMetaErrors.Free;
  DFA.Free;
  Tab.Free;
  inherited;
end;

function TCocoCompiler.Compile(const ResName: String): Boolean;
begin
  if fFlagStack<>nil then
    with fFlagStack do while Count>0 do Pop;
  FreeAndNil(fErrors);
  FreeAndNil(fMetaErrors);
  Parser.ClearOutputs;
  Tab.Reinit;
  DFA.Reinit;
  GenFlag := True;
  if Generator<>nil then
    Generator.Clear;

  if ResorceSystem.ResourceExists(ResName) then
  begin
    Parser.SetSourceFileName(ResName);
    Parser.Execute;
    Result := Generate and Parser.Successful;
  end else Result := False;
end;

function TCocoCompiler.Generate: Boolean;
var fn: String;
begin
  with DFA do
    if DirtyDFA then MakeDeterministic;
  fn := Tab.FrameName;
  with ResorceSystem do
  if not ResourceExists(fn) then
  begin
    fn := AbsoluteURL(Parser.SrcName,fn);
    if not ResourceExists(fn) then
    begin
      fn := AbsoluteURL(ExePath,Tab.FrameName);
      if not ResourceExists(fn) then
      begin
        Parser.SemErrorInLine(-1,0,Format('Frame file "%s" is not found',[Tab.FrameName]));
        Result := False;
        Exit;
      end;
    end;
  end;
  FrameName := fn;
  Execute;
  Result := ErrorCount=0;
end;

procedure TCocoCompiler.setFrameName(const Value: String);
begin
  if fFrameName<>Value then
  begin
    fFrameName := Value;
    if ResorceSystem.ResourceExists(Value) then
      TCocoRScanner(Scanner).SetSource(ResorceSystem.GetResString(Value));
  end;
end;

function _LineCompare(Item1, Item2: Pointer): Integer;
begin
  Result := Cardinal(TCocoRError(Item1).line)-Cardinal(TCocoRError(Item2).line);
end;

function TCocoCompiler.getSortedErrors: TList;
begin
  if (fErrors<>nil)and(fErrors.Count>0) then
    fErrors.Sort(_LineCompare);
  Result := fErrors;
end;

procedure TCocoCompiler.AddToErrorList(var list: TObjectList; aErrorType,aErrorCode, aLine,aCol: Integer;
      const aMsg, aData: string);
var err: TCocoRError;
begin
  err := TCocoRError.Create;
  with err do
  begin
    ErrorType := aErrorType;
    ErrorCode := aErrorCode;
    Line := aLine;
    Col := aCol;
    Msg := aMsg;
    Data := aData;
  end;
  if list=nil then list := TObjectList.Create;
  list.Add(err);
end;      

procedure TCocoCompiler.ErrorHandler(Sender: TObject; aErrorType, aErrorCode,
  aLine, aCol: Integer; const aMsg, aData: string);
begin
  AddToErrorList(fErrors,aErrorType,aErrorCode,aLine,aCol,aMsg,aData);
end;

procedure TCocoCompiler.MetaErrorHandler(Sender: TObject; aErrorType,aErrorCode, aLine,aCol: Integer;
      const aMsg, aData: string);
begin
  AddToErrorList(fMetaErrors,aErrorType,aErrorCode,aLine,aCol,aMsg,aData);
end;

function TCocoCompiler.PeakFlag: Boolean;
begin
  if (fFlagStack<>nil)and(fFlagStack.Count>0) then
    Result := Boolean(Integer(fFlagStack.Peek))
  else Result := True;
end;

function TCocoCompiler.PopFlag: Boolean;
begin
  if (fFlagStack<>nil)and(fFlagStack.Count>0) then
    Result := Boolean(Integer(fFlagStack.Pop))
  else Result := True;
end;

procedure TCocoCompiler.PushFlag;
begin
  if fFlagStack=nil then
    fFlagStack := TStack.Create;
  fFlagStack.Push(Pointer(GenFlag));
end;

procedure TCocoCompiler.PrintText;
var pos: TSymbolRec;
  ptr,I,endP: PChar;
  hasNewLine: Boolean;
begin
  pos := NextSymbol^;
  TCocoRScanner(Scanner).SkipTo(MetaKey);
  if GenFlag then
  begin
    Inc(pos.Beg,pos.Len);
    pos.Len := TCocoRScanner(Scanner).BufferPosition-pos.Beg;
    if pos.Len<=0 then Exit; 
    ptr := Scanner.GetSymbolPtr(@pos);
    if ptr<>nil then
    begin
      endP := ptr+pos.Len;
      I := ptr;
      hasNewLine := False;
      while I<>endP do
      begin
        if (I^=#13)or(I^=#10)  then
          hasNewLine := True
        else if (I^<>' ')and(I^<>#9) then
          Break;
        Inc(I);
      end;
      if I<>endP then
        Generator.PrintSemanticCode(ptr,-1,0,pos.Len)
      else if hasNewLine then
        Generator.PrintLn;
    end;
  end;
end;

procedure TCocoCompiler.PrintVar(const name: String);
var pos: PSymbol;
    newPos,oldPos: TSymbolRec;
    ptr,ptr2: PChar;
    oldCh: Char;
    hasMeta: Boolean;
    BMark, OldSrc: String;
    WC,EC : Integer;
begin
  pos := Tab.TemplateVars[name];
  if (pos<>nil)and(pos^.Len>0) then
  begin
    ptr := Parser.Scanner.GetSymbolPtr(pos);
    oldCh := (ptr+pos.Len)^;
    (ptr+pos.Len)^ := #0;
    ptr2 := StrPos(ptr,PChar(MetaKey));
    hasMeta := ptr2<>nil;
    (ptr+pos.Len)^ := oldCh;
    if hasMeta then
    begin
      BMark := Bookmark;
      OldSrc := Scanner.Source;
      Scanner.GetSourcePosition(oldPos);
      WC := WarnCount; EC := ErrorCount;
      try
        newPos := pos^;
        newPos.Len := ptr2-ptr;
        Generator.PrintFragment(@newPos);
        newPos := pos^;
        Inc(newPos.Beg,ptr2-ptr);
        Dec(newPos.Len,ptr2-ptr);
        Scanner.SetSource(TCocoRScanner(Parser.Scanner).Source,@newPos);
        Reinit;
        _Body;
      finally
        Scanner.SetSource(OldSrc,@oldPos);
        GotoBookmark(BMark);
        WarnCount := WC; ErrorCount := EC;
      end;
    end else
      Generator.PrintFragment(pos);
  end;
end;


procedure TCocoCompiler._CocoCompiler;
begin
  Expect(TARGETSym);
  _TargetClause;
                          if (Generator=nil) then Exit;
  _Body;
  Expect(_EOFSYMB);
end;

procedure TCocoCompiler._TargetClause;
 var aClass: TParserGeneratorClass; 
begin
  Expect(identSym);
           if not FindParserGeneratorClass(LexName,aClass) then
           begin
              SemError(200,LexName);
              Exit;
           end; 
           if (Generator<>nil) then
             if Generator.ClassType=aClass then Exit
             else FreeAndNil(Generator);
           Generator := aClass.Create;
           Generator.Coco := Parser;
        
end;

procedure TCocoCompiler._Body;
begin
  while (CurrentInputSymbol=_less_barSym) do
  begin
    _TemplateBlock;
  end;
                          PrintText; 
end;

procedure TCocoCompiler._TemplateBlock;
 var pred: Boolean; 
begin
  Expect(_less_barSym);
  if (CurrentInputSymbol=_hashSym) then
  begin
       Get;
       while InSet(CurrentInputSymbol,0) do
       begin
         Get;
       end;
  end
  else if (CurrentInputSymbol=_querySym) then
  begin
       Get;
       _Predicate(pred);
                             PushFlag; 
                             GenFlag := GenFlag and pred;   
  end
  else if (CurrentInputSymbol=ELSESym) then
  begin
       Get;
                             if PeakFlag then GenFlag := not GenFlag; 
  end
  else if (CurrentInputSymbol=ENDSym) then
  begin
       Get;
       while InSet(CurrentInputSymbol,0) do
       begin
         Get;
       end;
                             GenFlag := PopFlag; 
  end
  else if (CurrentInputSymbol=ERRORSym) then
  begin
       Get;
       Expect(stringSym);
                             if GenFlag then Parser.SemError(-1,LexString); 
  end
  else if (CurrentInputSymbol=_equalSym) then
  begin
       Get;
       Expect(identSym);
                             if GenFlag then PrintVar(LexName);  
  end
  else if (CurrentInputSymbol=_bangSym) then
  begin
       Get;
       _TargetCode;
  end
  else if (CurrentInputSymbol=_atSym) then
  begin
       Get;
       if (CurrentInputSymbol=identSym) then
       begin
            Get;
                             if GenFlag then Parser.SetOutput(LexName); 
       end
       else if (CurrentInputSymbol=stringSym) then
       begin
            Get;
                             if GenFlag then Parser.SetOutputFilename(LexName); 
       end
       else SynError(1);
       if (CurrentInputSymbol=_lparenSym) then
       begin
         Get;
         _Settings;
         Expect(_rparenSym);
       end;
  end
  else SynError(1);
                             PrintText; 
  Expect(_bar_greaterSym);
end;

procedure TCocoCompiler._Predicate(var value: Boolean );
 var v2: Boolean; 
begin
  _BoolTerm(value);
  while (CurrentInputSymbol=ORSym) do
  begin
    Get;
    _BoolTerm(v2);
                              value := Value or v2; 
  end;
end;

procedure TCocoCompiler._TargetCode;
begin
  if (CurrentInputSymbol=DELETABLESLISTSym) then
  begin
       Get;
                        if GenFlag then Generator.PrintListOfDeletableSymbols;  
  end
  else if (CurrentInputSymbol=FIRSTFOLLOWLISTSym) then
  begin
       Get;
                        if GenFlag then Generator.PrintStartFollowerSets;       
  end
  else if (CurrentInputSymbol=XREFLISTSym) then
  begin
       Get;
                        if GenFlag then Generator.PrintXRef;                    
  end
  else if (CurrentInputSymbol=LISTINGSym) then
  begin
       Get;
                        if GenFlag then
                        with Generator do
                        begin
                          PrintLn(Format('%d errors and %d warnings',[Parser.ErrorCount,Parser.WarnCount]));
                          PrintListing(getSortedErrors);
                        end;
  end
  else if (CurrentInputSymbol=SYMBOLTABLESym) then
  begin
       Get;
                        if GenFlag then Generator.PrintSymbolTable;             
  end
  else if (CurrentInputSymbol=STATESSym) then
  begin
       Get;
                        if GenFlag then Generator.PrintStates;                  
  end
  else if (CurrentInputSymbol=NODESSym) then
  begin
       Get;
                        if GenFlag then Generator.PrintNodes;                   
  end
  else if (CurrentInputSymbol=GRAMMASym) then
  begin
       Get;
                        if GenFlag then 
                        with Parser.tab do 
                        if gramSy<>nil then 
                          Generator.Print(gramSy.Name); 
  end
  else if (CurrentInputSymbol=PARSERDECLARATIONSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintParserDeclarations;   
  end
  else if (CurrentInputSymbol=TOKENSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintTokens;               
  end
  else if (CurrentInputSymbol=INITSTARTSTATESSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintInitStartStates;      
  end
  else if (CurrentInputSymbol=COMMENTSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintComments;             
  end
  else if (CurrentInputSymbol=INITLITERALSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintInitLiterals;         
  end
  else if (CurrentInputSymbol=INITSYMSETSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintInitSymSets;          
  end
  else if (CurrentInputSymbol=ERRORSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintErrors;               
  end
  else if (CurrentInputSymbol=SCANSYMSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintScanSym;               
  end
  else if (CurrentInputSymbol=IGNORESETSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintIgnoreSet;             
  end
  else if (CurrentInputSymbol=PARSERIMPLEMENTATIONSym) then
  begin
       Get;
                             if GenFlag then Generator.PrintParserImplementation;
  end
  else if (CurrentInputSymbol=TOKENSTRINGSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintTokenStrings;          
  end
  else if (CurrentInputSymbol=ANYANDSYNCSETSSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintAnyAndSyncSets;        
  end
  else if (CurrentInputSymbol=PRAGMASSym) then
  begin
       Get;
                           if GenFlag then Generator.PrintPragmas;               
  end
  else if (CurrentInputSymbol=NOSYMSym) then
  begin
       Get;
                           if GenFlag then 
                           with Generator do Print(GenTokenName(Parser.tab.noSym.index));  
  end
  else if (CurrentInputSymbol=identSym) then
  begin
       Get;
  end
  else SynError(2);
end;

procedure TCocoCompiler._Settings;
begin
  _Param;
  while (CurrentInputSymbol=_commaSym) do
  begin
    Get;
    _Param;
  end;
end;

procedure TCocoCompiler._Param;
begin
  Expect(identSym);
  Expect(_equalSym);
  if (CurrentInputSymbol=stringSym) then
  begin
       Get;
  end
  else if (CurrentInputSymbol=numberSym) then
  begin
       Get;
  end
  else SynError(3);
end;

procedure TCocoCompiler._BoolTerm(var value: Boolean );
 var v2: Boolean; 
begin
  _BoolFactor(value);
  while (CurrentInputSymbol=ANDSym) do
  begin
    Get;
    _BoolFactor(v2);
                             value := Value and v2; 
  end;
end;

procedure TCocoCompiler._BoolFactor(var value: Boolean );
begin
  if (CurrentInputSymbol=identSym) then
  begin
       Get;
                                value := False; 
  end
  else if InSet(CurrentInputSymbol,1) then
  begin
       _SystemPridicate(value);
  end
  else if (CurrentInputSymbol=NOTSym) then
  begin
       Get;
       _BoolFactor(value);
                                value := not value; 
  end
  else if (CurrentInputSymbol=DEFINEDSym) then
  begin
       Get;
       Expect(_lparenSym);
       Expect(identSym);
                                value := Parser.tab.TemplateVars[LexName]<>nil; 
       Expect(_rparenSym);
  end
  else if (CurrentInputSymbol=TRUESym) then
  begin
       Get;
                                value := True; 
  end
  else if (CurrentInputSymbol=FALSESym) then
  begin
       Get;
                                value := False; 
  end
  else if (CurrentInputSymbol=_lparenSym) then
  begin
       Get;
       _Predicate(value);
       Expect(_rparenSym);
  end
  else SynError(4);
end;

procedure TCocoCompiler._SystemPridicate(var value: Boolean);
begin
  if (CurrentInputSymbol=OKSym) then
  begin
       Get;
                         value := Parser.Successful;          
  end
  else if (CurrentInputSymbol=DELETABLESEXISTSym) then
  begin
       Get;
                         value := Parser.tab.DeletableCount>0;
  end
  else if (CurrentInputSymbol=IGNORECASESym) then
  begin
       Get;
                         value := Parser.tab.IgnoreCase;      
  end
  else if (CurrentInputSymbol=IGNORESETSym) then
  begin
       Get;
                         with Parser.tab do 
                         value := (IgnoredChars<>nil)and not IgnoredChars.IsEmpty; 
  end
  else if (CurrentInputSymbol=COMMENTSSym) then
  begin
       Get;
                         value := Parser.DFA.CommentCount>0;
  end
  else if (CurrentInputSymbol=INITSYMSETSSym) then
  begin
       Get;
                         value := Generator.hasSymSets;     
  end
  else if (CurrentInputSymbol=HASHOMOGRAPHSym) then
  begin
       Get;
                         value := Parser.Tab.CountHomographs>0;
  end
  else if (CurrentInputSymbol=GENSCANNERSym) then
  begin
       Get;
                         value := Parser.genScanner;        
  end
  else if (CurrentInputSymbol=PRAGMASSym) then
  begin
       Get;
                         value := Parser.Tab.PragmaCount>0; 
  end
  else if (CurrentInputSymbol=HASCTXMOVESSym) then
  begin
       Get;
                         value := Parser.DFA.HasCtxMoves;   
  end
  else if (CurrentInputSymbol=HASWARNINGSSym) then
  begin
       Get;
                         value := Parser.WarnCount>0;       
  end
  else SynError(5);
end;



function TCocoCompiler.TokenToString(n: Integer): String;
const TokenStrings: array[0.._NOSYMB] of String = ('EOF'
	,'ident'	,'string'	,'number'	,'"TARGET"'	,'"<|"'
	,'"#"'	,'"?"'	,'"ELSE"'	,'"END"'	,'"ERROR"'
	,'"="'	,'"!"'	,'"@"'	,'"("'	,'")"'
	,'"|>"'	,'"DELETABLESLIST"'	,'"FIRSTFOLLOWLIST"'	,'"XREFLIST"'	,'"LISTING"'
	,'"SYMBOLTABLE"'	,'"STATES"'	,'"NODES"'	,'"GRAMMA"'	,'"PARSERDECLARATIONS"'
	,'"TOKENS"'	,'"INITSTARTSTATES"'	,'"COMMENTS"'	,'"INITLITERALS"'	,'"INITSYMSETS"'
	,'"ERRORS"'	,'"SCANSYM"'	,'"IGNORESET"'	,'"PARSERIMPLEMENTATION"'	,'"TOKENSTRINGS"'
	,'"ANYANDSYNCSETS"'	,'"PRAGMAS"'	,'"NOSYM"'	,'","'	,'"OR"'
	,'"AND"'	,'"NOT"'	,'"DEFINED"'	,'"TRUE"'	,'"FALSE"'
	,'"OK"'	,'"DELETABLESEXIST"'	,'"IGNORECASE"'	,'"HASHOMOGRAPH"'	,'"GENSCANNER"'
	,'"HASCTXMOVES"'	,'"HASWARNINGS"'  ,'not');
begin
  if n in [0.._NOSYMB] then
    Result := TokenStrings[n]
  else Result := '?';
end;

function TCocoCompiler.ErrorMessage(ErrorType, ErrorCode: Integer; const data: string): String;
begin
  case ErrorCode of
	1 : Result := 'invalid TemplateBlock';
	2 : Result := 'invalid TargetCode';
	3 : Result := 'invalid Param';
	4 : Result := 'invalid BoolFactor';
	5 : Result := 'invalid SystemPridicate';

               
  200: Result := Format('Unknown parser target "%s"',[data]);
 
    else Result := inherited ErrorMessage(ErrorType, ErrorCode,data);
  end;
end;



function TCocoCompiler.Execute: Boolean;
begin
  Reinit;
  _CocoCompiler;
  Result := Successful;
end;


function TCocoCompiler.CreateScanner: TBaseScanner;
begin
  Result := TCocoCompilerScanner.Create(Self);
  if CocoCompilerST=nil then
  begin
    CocoCompilerST := TStartTable.Create;
    with CocoCompilerST do
    begin
	  FillRange(65, 90, 1);  States[95] := 1;  FillRange(48, 57, 4);  States[34] := 2;
	  States[60] := 5;  States[35] := 7;  States[63] := 8;  States[61] := 9;  States[33] := 10;
	  States[64] := 11;  States[40] := 12;  States[41] := 13;  States[124] := 14;  States[44] := 16;

    end;
    CocoCompilerLiterals := CreateLiterals(False,
	['TARGET','ELSE','END','ERROR','DELETABLESLIST','FIRSTFOLLOWLIST','XREFLIST','LISTING','SYMBOLTABLE','STATES','NODES'
		,'GRAMMA','PARSERDECLARATIONS','TOKENS','INITSTARTSTATES','COMMENTS','INITLITERALS','INITSYMSETS','ERRORS','SCANSYM'
		,'IGNORESET','PARSERIMPLEMENTATION','TOKENSTRINGS','ANYANDSYNCSETS','PRAGMAS','NOSYM','OR','AND','NOT','DEFINED'
		,'TRUE','FALSE','OK','DELETABLESEXIST','IGNORECASE','HASHOMOGRAPH','GENSCANNER','HASCTXMOVES','HASWARNINGS'],
	[TARGETSym,ELSESym,ENDSym,ERRORSym,DELETABLESLISTSym,FIRSTFOLLOWLISTSym,XREFLISTSym,LISTINGSym,SYMBOLTABLESym,STATESSym
		,NODESSym,GRAMMASym,PARSERDECLARATIONSSym,TOKENSSym,INITSTARTSTATESSym,COMMENTSSym,INITLITERALSSym,INITSYMSETSSym
		,ERRORSSym,SCANSYMSym,IGNORESETSym,PARSERIMPLEMENTATIONSym,TOKENSTRINGSSym,ANYANDSYNCSETSSym,PRAGMASSym,NOSYMSym
		,ORSym,ANDSym,NOTSym,DEFINEDSym,TRUESym,FALSESym,OKSym,DELETABLESEXISTSym,IGNORECASESym,HASHOMOGRAPHSym,GENSCANNERSym
		,HASCTXMOVESSym,HASWARNINGSSym]
     );
  end;
  with TCocoCompilerScanner(Result) do
  begin
    CaseInsensitive := True;  
    noSym := _NOSYMB;
    StartState := CocoCompilerST;
    Literals := CocoCompilerLiterals;
  end;
end;


constructor TCocoCompiler.Create(AOwner: TComponent);
begin
  
  inherited;

  if Length(CocoCompilerSymSets)=0 then
  InitSymSets(CocoCompilerSymSets,[
    	{ 0} identSym, stringSym, numberSym, TARGETSym, _less_barSym, _hashSym, _querySym, ELSESym, ENDSym, ERRORSym, _equalSym, _bangSym, _atSym, _lparenSym, _rparenSym, DELETABLESLISTSym, FIRSTFOLLOWLISTSym, XREFLISTSym, LISTINGSym, SYMBOLTABLESym, STATESSym, NODESSym, GRAMMASym, PARSERDECLARATIONSSym, TOKENSSym, INITSTARTSTATESSym, COMMENTSSym, INITLITERALSSym, INITSYMSETSSym, ERRORSSym, SCANSYMSym, IGNORESETSym, PARSERIMPLEMENTATIONSym, TOKENSTRINGSSym, ANYANDSYNCSETSSym, PRAGMASSym, NOSYMSym, _commaSym, ORSym, ANDSym, NOTSym, DEFINEDSym, TRUESym, FALSESym, OKSym, DELETABLESEXISTSym, 
IGNORECASESym, HASHOMOGRAPHSym, GENSCANNERSym, HASCTXMOVESSym, HASWARNINGSSym, _NOSYMB, -1,
	{ 1} COMMENTSSym, INITSYMSETSSym, IGNORESETSym, PRAGMASSym, OKSym, DELETABLESEXISTSym, IGNORECASESym, HASHOMOGRAPHSym, GENSCANNERSym, HASCTXMOVESSym, HASWARNINGSSym
  ]); 
  SymSets := CocoCompilerSymSets;
            
  Self.OnError := MetaErrorHandler;
  Parser := TCoco.Create(Self);
  Parser.OnError := ErrorHandler;
  Tab := TSymbolTable.Create(Parser);
  DFA := TAutomaton.Create(Parser,Tab);
  Parser.tab := Tab;
  Parser.dfa := DFA;
   
end;

end.

